package magicboard.model
{
  import flash.display.Graphics;
  import flash.geom.Point;
  
  import magicboard.model.Vector;
  
  public class LineSegment implements GeometryObject
  {
    // --------------------------------------------------------------------------------------------
    public function LineSegment(a:Point, b:Point){
      _p1 = a;
      _p2 = b;
    }

	  // --------------------------------------------------------------------------------------------
	  public function get P1():Point{return _p1;}
	  public function get P2():Point{return _p2;}
	  
	  // --------------------------------------------------------------------------------------------
		public function draw(g:Graphics):void{

    	g.moveTo(_p1.x, _p1.y);
   		g.lineTo(_p2.x, _p2.y);
		}
		
	  // --------------------------------------------------------------------------------------------
		public function getLineLength():Number{
		  return Vector.points2Vector(_p1,_p2).getLength();
		}

	  // --------------------------------------------------------------------------------------------
		public function toString():String{
		  return "Line segment";
		}

	  // --------------------------------------------------------------------------------------------
		public function saveToString():String{
			return "line: (" + _p1.x + "," + _p1.y + "), (" + _p2.x + "," + _p2.y + ")";
		}

	  // --------------------------------------------------------------------------------------------
		public function getType():String{
			return "line";
		}

    // --------------------------------------------------------------------------------------------
    /** 
    * Calculate distance from point to the line defined by this segment
    * Based on:
    * http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm 
    */
    public function distanceToLine(p:Point):Number
    {
      var v:Vector = Vector.points2Vector(_p1,_p2);
      var c2:Number = Vector.dot(v,v);

      var w:Vector = Vector.points2Vector(_p1,p);
      var c1:Number = Vector.dot(w,v);
      var b:Number = c1/c2; 
      var pb:Point = new Point(_p1.x + b * v.x, _p1.y + b * v.y);             //      Point Pb = L.P0 + b * v;

      return p.subtract(pb).length;
    }

		// --------------------------------------------------------------------------------------------
		/** Calculate distance^2 from point to this segment 	 */
		public function distanceToSegment2(point:Point):Number {
			
			var v:Vector = Vector.points2Vector(_p1, _p2);
    	var w:Vector = Vector.points2Vector(_p1, point);

    	var c1:Number = Vector.dot(w,v);
    
    	if ( c1 <= 0 )
    		return w.getLength2();

    	var c2:Number = Vector.dot(v,v);
    	if ( c2 <= c1 )
        return Vector.points2Vector(_p2, point).getLength2();

    	var b:Number = c1 / c2;
    	
    	var pb:Point = new Point(_p1.x + b * v.x, _p1.y + b * v.y);
    	
    	return Vector.points2Vector(pb, point).getLength2();
		}
		
	  // --------------------------------------------------------------------------------------------
		public function toVector():Vector{
		  return Vector.points2Vector(_p1,_p2);
		}

    // --------------------------------------------------------------------------------------------
    // Private members
    private var _p1:Point;
    private var _p2:Point;
  }
}